<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>WebGL-4.动态绘制三角形</title>
</head>
<body>
  <canvas id="glcanvas" width="640" height="480"></canvas>
  <script type="shader-source" id="vertexShader">
    // 设置浮点精度为中等精度
    precision mediump float;
    // 接收点在canvas坐标系的坐标
    attribute vec2 a_Position;
    // 接收canvas的宽高
    attribute vec2 a_Screen_Size;
    void main() {
      // 将屏幕坐标系转成裁剪坐标系
      vec2 position = (a_Position / a_Screen_Size) * 2.0 - 1.0;
      // canvas的 Y 轴坐标方向和 设备坐标系的相反。
      position = position * vec2(1.0, -1.0);
      gl_Position = vec4(position, 0.0, 1.0);

      // 声明要绘制的点的大小
      gl_PointSize = 10.0;
    }
  </script>
  <script type="shader-source" id="fragmentShader">
    // 设置浮点精度为中等精度
    precision mediump float;
    // 接收从js传过来的颜色值(RGBA)
    uniform vec4 u_Color;
    void main() {
      // 将不同的颜色表示转换成webgl的颜色表示【0，1】
      vec4 color = u_Color / vec4(255, 255, 255, 1);
      // 设置像素颜色为红色
      gl_FragColor = color;
    }
  </script>
  <script id="webgl-helper">
    /**
     * 创建着色器
     * @param shaderType 着色器类型
     * @param sourceId 着色器源码id
     * @return shader 着色器
    */
    function createShader(shaderType, sourceId) {
      // 获取着色器源码
      var shaderSource = document.querySelector(sourceId).innerHTML;
      // 创建着色器
      var shader = this.createShader(shaderType);
      // 将源码与着色器绑定
      this.shaderSource(shader, shaderSource);
      // 编译着色器
      this.compileShader(shader);
      return shader;
    }

    /**
     * 创建着色器程序&绑定着色器
     * @param arguments 着色器数组
     * @return program 着色器程序
    */
    function createProgram() {
      // 创建周色器程序
      var program = this.createProgram();
      for (var i = 0; i < arguments.length; i++) {
        // 将着色器挂在着色器程序上
        this.attachShader(program, arguments[i]);
      }
      // 连接着色器程序
      this.linkProgram(program);
      return program;
    }
  </script>
  <script>
    (function() {
      var canvas = document.getElementById('glcanvas');
      var gl = canvas.getContext('webgl');

      // 创建顶点着色器对象
      var vertexShader = createShader.call(gl, gl.VERTEX_SHADER, '#vertexShader');
      // 创建片元着色器对象
      var fragmentShader = createShader.call(gl, gl.FRAGMENT_SHADER, '#fragmentShader');
      // 创建着色器程序
      var program = createProgram.apply(gl, [vertexShader, fragmentShader]);

      // 启用着色器程序（通常有多个程序) 使用前先启动
      gl.useProgram(program);

      // 获取顶点着色器的变量
      var aPosition = gl.getAttribLocation(program, 'a_Position');
      var aScreenSize = gl.getAttribLocation(program, 'a_Screen_Size');
      // 找到片元着色器的变量
      var uColor = gl.getUniformLocation(program, 'u_Color');
      // 为顶点着色器传递canvas宽高
      gl.vertexAttrib2f(aScreenSize, canvas.width, canvas.height);
      // 传递该点的颜色
      gl.uniform4f(uColor, 255, 255, 255, 1);

      // 创建一个缓冲区
      var buffer = gl.createBuffer();
      // 绑定缓冲区
      gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

      // 启用属性
      gl.enableVertexAttribArray(aPosition);

      // 从缓冲区读取数据
      gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);

      // 三角形的三个点
      var positions = [];
      canvas.addEventListener('click', function(event) {
        positions.push(event.pageX, event.pageY);
        if (positions.length % 6 === 0) {
          // 往缓冲区内写入数据 Float32Array是因为glsl是强类型的，所以需要将数组同样转成抢类型
          gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
          draw();
        }
      }, false);
      // 绘制三角形
      function draw() {
        // 设置清空画布的颜色为黑色
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        // 用上一步设置的颜色清空画布
        gl.clear(gl.COLOR_BUFFER_BIT);
        if (positions.length > 0) {
          // 绘制图像的类型，从顶点数组的哪个位置开始绘制，绘制几次
          gl.drawArrays(gl.TRIANGLES, 0, positions.length / 2);
        }
      }
      draw();
    })();
  </script>
</body>
</html>